/**
 * OSAmI: Open Source Ambient Intelligence
 * Copyright (C) 2010 Bull S.A.S.
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 */

package org.osami.gateway.display.internal;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpUtils;

import org.apache.felix.ipojo.annotations.Bind;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Instantiate;
import org.apache.felix.ipojo.annotations.Invalidate;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.Unbind;
import org.apache.felix.ipojo.annotations.Validate;
import org.osami.gateway.identity.Identity;
import org.osami.gateway.identity.IdentityProvider;
import org.osami.gateway.watteco.interfaces.IWattecoSmartplug;
import org.osami.gateway.watteco.interfaces.IWattecoSmartplugIPv4;
import org.osami.gateway.watteco.interfaces.IWattecoSmartplugIPv6;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;

@Component
@Instantiate
public class PowerPlugsViewServlet extends HttpServlet {

    /**
     * serial version UID.
     */
    private static final long serialVersionUID = -9031597641367237767L;

    private List<IWattecoSmartplug> smartplugs;

    @Requires
    private HttpContext context;

    @Requires
    private HttpService httpService;

    @Requires(optional = true)
    private IdentityProvider identityProvider;

    public PowerPlugsViewServlet() {
        smartplugs = new LinkedList<IWattecoSmartplug>();
    }

    @Validate
    public void start() throws ServletException, NamespaceException {
        this.httpService.registerServlet(ServletPaths.POWERPLUGS, this, null, this.context);
    }

    @Invalidate
    public void stop() {
        this.httpService.unregister(ServletPaths.POWERPLUGS);
    }

    @Bind(aggregate = true, optional=true)
    public void bindPowerPlug(final IWattecoSmartplug smartplug) {
        System.out.print("PowerPlugsViewServlet: bindPowerPlug ");
        if (smartplug instanceof IWattecoSmartplugIPv4) {
            System.out.print("IPv4");
        }
        else if (smartplug instanceof IWattecoSmartplugIPv6) {
            System.out.print("IPv6");
        }
        System.out.println();
        smartplugs.add(smartplug);
    }

    @Unbind
    public void unbindPowerPlug(final IWattecoSmartplug smartplug) {
        System.out.print("PowerPlugsViewServlet: unbindPowerPlug ");
        if (smartplug instanceof IWattecoSmartplugIPv4) {
            System.out.print("IPv4");
        }
        else if (smartplug instanceof IWattecoSmartplugIPv6) {
            System.out.print("IPv6");
        }
        System.out.println();
        smartplugs.remove(smartplug);
    }

    @Override
    protected synchronized void doGet(final HttpServletRequest req,
            final HttpServletResponse resp) throws ServletException,
            IOException {
        PrintWriter writer = resp.getWriter();
        String query = req.getQueryString();

        if (query != null) {
            // TODO a bit strange ... Moreover HttpUtils is deprecated ...
            // Why using a simple req.getParameter("AAA"):String or req.getParameterValues("AAA"):String[] ?
            Hashtable<String, String[]> params = HttpUtils.parseQueryString(query);
            for (String key : params.keySet()) {
                if (key.equals(Constants.SWITCH_ON)) {
                    for (String val : params.get(key)) {
                        for (IWattecoSmartplug smartplug : smartplugs) {
                            if (smartplug.getID().equals(val)) {
                                smartplug.switchOn();
                            }
                        }
                    }
                }
                else if (key.equals(Constants.SWITCH_OFF)) {
                    for (String val : params.get(key)) {
                        for (IWattecoSmartplug smartplug : smartplugs) {
                            if (smartplug.getID().equals(val)) {
                                smartplug.switchOff();
                            }
                        }
                    }
                }
                else if (key.equals(Constants.TOGGLE_SWITCH)) {
                    for (String val : params.get(key)) {
                        for (IWattecoSmartplug smartplug : smartplugs) {
                            if (smartplug instanceof IWattecoSmartplugIPv6) {
                                if (smartplug.getID().equals(val)) {
                                    smartplug.toggleSwitch();
                                }
                            }
                        }
                    }
                }
            }
        }

        writer.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">");
        writer.println("<html lang=\"en\">");

        // HTML Head
        // ---------------------------------------------------
        writer.println("<head>");
        writer.println("<title>Power plugs visible from the gateway</title>");
        writer.println("<link href=\"/resource/css/designSensor.css\" rel=\"stylesheet\" type=\"text/css\" />");
        writer.println("</head>");

        // HTML Body
        // ---------------------------------------------------
        writer.println("<body>");
        writer.println("<h1>Power plugs visible from the gateway</h1><hr/>");

        printPowerPlugsTable(writer);

        writer.println("<p>Last refresh finished at " + new Date().toString() + "</p>");
        writer.println("<a href=\"" + ServletPaths.POWERPLUGS + "\">Refresh list</a>");

        writer.println("<hr/>");
        writer.println("<a href=\"" + ServletPaths.INDEX + "\">Go back to main page</a>\n");
        writer.println("</body>");
        writer.println("</html>");
    }

    private void printPowerPlugsTable(PrintWriter writer) {
        writer.println("<table width='100%' cellpadding='0'>");
        // Print table headers
        writer.println("<thead><tr>");
        // Print each column name here
        printPowerPlugsTableHeaders(writer);
        writer.println("</tr></thead>");

        // Print table body
        writer.println("<tbody>");
        // Print each power plug in its own row
        for (IWattecoSmartplug smartplug : smartplugs) {
            printPowerPlugsRow(writer, smartplug);
        }
        writer.println("</tbody>");
        writer.println("</table>");
    }

    private void printPowerPlugsTableHeaders(PrintWriter writer) {
        writer.println("<th>Identifier</th>");
        writer.println("<th>Friendly name</th>");
        writer.println("<th>Consumption since last refresh</th>");
        writer.println("<th>Actions</th>");
    }

    private void printPowerPlugsRow(PrintWriter writer, IWattecoSmartplug smartplug) {
        writer.println("<tr>");
        String nodeId = smartplug.getID();
        String identityName = "&lt;no friendly name&gt;";

        printTableCell(writer, nodeId);

        if (this.identityProvider != null) {
            final Identity identity = this.identityProvider.getBoundIdentity(nodeId);
            if (identity != null) {
                final String identityName2 = identity.getName();
                if (identityName2 != null && !identityName2.equals("")) {
                    identityName = identityName2;
                }
            }
        }

        printTableCell(writer, identityName);

        try {
            printTableCell(writer, Integer.toString(smartplug.getMeasurement()));
        }
        catch (Exception e) {
            printTableCell(writer, "&lt;error reading measurement&gt;");
        }

        String content =  "<a href=\"" + ServletPaths.POWERPLUGS + "?" + Constants.SWITCH_ON + "=" + nodeId + "\">Switch on</a>&nbsp;&nbsp;"
                          + "&nbsp;&nbsp;<a href=\"" + ServletPaths.POWERPLUGS + "?" + Constants.SWITCH_OFF + "=" + nodeId + "\">Switch off</a>";

        if (smartplug instanceof IWattecoSmartplugIPv6) {
            content += "&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"" + ServletPaths.POWERPLUGS + "?" + Constants.TOGGLE_SWITCH + "=" + nodeId + "\">Toggle switch</a>";
        }

        printTableCell(writer,  content);

        writer.println("</tr>");
    }

    private void printTableCell(PrintWriter writer, String content) {
        writer.println("<td>" + content + "</td>");
    }
}

